#ifndef FGI_CLUSTER_CLIENT_MODULE_H
#define FGI_CLUSTER_CLIENT_MODULE_H

#include <iostream>
#include "IModule.h"
#include "INetModule.h"
//#include "Common/Core/NFConsistentHash.hpp"
namespace FragrantGrass
{
	enum ConnectDataState
	{
		DISCONNECT,
		CONNECTING,
		NORMAL,
		RECONNECT,
	};

	struct ConnectData
	{
		ConnectData()
		{
			nGameID = 0;
			nPort = 0;
			strName = "";
			strIP = "";
			eServerType = FG_ST_NONE;
			eState = ConnectDataState::DISCONNECT;
			mLastActionTime = 0;
			nWorkLoad = 0;
		}

		int nGameID;
		FG_SERVER_TYPES eServerType;
		std::string strIP;
		int nPort;
		int nWorkLoad;
		std::string strName;
		ConnectDataState eState;
		INT64 mLastActionTime;

		FG_SHARE_PTR<INetModule> mxNetModule;
	};

	class INetClientModule : public IModule
	{
		DECLARE_MODULE_NAME(INetClientModule)
	public:
		enum EConstDefine
		{
			EConstDefine_DefaultWeith = 500,
		};

		template<typename BaseType>
		bool AddReceiveCallBack(const FG_SERVER_TYPES eType, const uint16_t nMsgID, BaseType* pBase, void (BaseType::* handleRecieve)(const SOCK, const int, const char*, const uint32_t))
		{
			NET_MESSAGE_HANDLER_FUNCTOR functor = std::bind(handleRecieve, pBase, std::placeholders::_1, std::placeholders::_2, std::placeholders::_3, std::placeholders::_4);
			NET_MESSAGE_HANDLER_FUNCTOR_PTR functorPtr(new NET_MESSAGE_HANDLER_FUNCTOR(functor));

			AddReceiveCallBack(eType, nMsgID, functorPtr);

			return true;
		}

		template<typename BaseType>
		int AddReceiveCallBack(const FG_SERVER_TYPES eType, BaseType* pBase, void (BaseType::* handleRecieve)(const SOCK, const int, const char*, const uint32_t))
		{
			NET_MESSAGE_HANDLER_FUNCTOR functor = std::bind(handleRecieve, pBase, std::placeholders::_1, std::placeholders::_2, std::placeholders::_3, std::placeholders::_4);
			NET_MESSAGE_HANDLER_FUNCTOR_PTR functorPtr(new NET_MESSAGE_HANDLER_FUNCTOR(functor));

			AddReceiveCallBack(eType, functorPtr);

			return true;
		}

		template<typename BaseType>
		bool AddEventCallBack(const FG_SERVER_TYPES eType, BaseType* pBase, void (BaseType::* handler)(const SOCK, const FG_NET_EVENT, INet*))
		{
			NET_EVENT_HANDLER_FUNCTOR functor = std::bind(handler, pBase, std::placeholders::_1, std::placeholders::_2, std::placeholders::_3);
			NET_EVENT_HANDLER_FUNCTOR_PTR functorPtr(new NET_EVENT_HANDLER_FUNCTOR(functor));

			AddEventCallBack(eType, functorPtr);

			return true;
		}

		virtual int AddReceiveCallBack(const FG_SERVER_TYPES eType, NET_MESSAGE_HANDLER_FUNCTOR_PTR functorPtr) = 0;
		virtual int AddReceiveCallBack(const FG_SERVER_TYPES eType, const uint16_t nMsgID, NET_MESSAGE_HANDLER_FUNCTOR_PTR functorPtr) = 0;
		virtual int AddEventCallBack(const FG_SERVER_TYPES eType, NET_EVENT_HANDLER_FUNCTOR_PTR functorPtr) = 0;

		virtual void RemoveReceiveCallBack(const FG_SERVER_TYPES eType, const uint16_t nMsgID) = 0;
		////////////////////////////////////////////////////////////////////////////////

		virtual void AddServer(const ConnectData& xInfo) = 0;
		virtual int ExpandBufferSize(const unsigned int size = 1024 * 1024 * 20) = 0;

		////////////////////////////////////////////////////////////////////////////////
		virtual void SendByServerIDWithOutHead(const int nServerID, const uint16_t nMsgID, const std::string& strData) = 0;

		virtual void SendByServerID(const int nServerID, const uint16_t nMsgID, const std::string& strData) = 0;
		virtual void SendByServerID(const int nServerID, const uint16_t nMsgID, const std::string& strData, const GUID id) = 0;

		virtual void SendToAllServerWithOutHead(const uint16_t nMsgID, const std::string& strData) = 0;

		virtual void SendToAllServer(const uint16_t nMsgID, const std::string& strData) = 0;
		virtual void SendToAllServer(const uint16_t nMsgID, const std::string& strData, const GUID id) = 0;

		virtual void SendToAllServerWithOutHead(const FG_SERVER_TYPES eType, const uint16_t nMsgID, const std::string& strData) = 0;

		virtual void SendToAllServer(const FG_SERVER_TYPES eType, const uint16_t nMsgID, const std::string& strData) = 0;
		virtual void SendToAllServer(const FG_SERVER_TYPES eType, const uint16_t nMsgID, const std::string& strData, const GUID id) = 0;

		virtual void SendToServerByPB(const int nServerID, const uint16_t nMsgID, const google::protobuf::Message& xData) = 0;
		virtual void SendToServerByPB(const int nServerID, const uint16_t nMsgID, const google::protobuf::Message& xData, const GUID id) = 0;

		virtual void SendToAllServerByPB(const uint16_t nMsgID, const google::protobuf::Message& xData) = 0;

		virtual void SendToAllServerByPB(const FG_SERVER_TYPES eType, const uint16_t nMsgID, const google::protobuf::Message& xData) = 0;

		////////////////////////////////////////////////////////////////////////////////

		virtual void SendBySuitWithOutHead(const FG_SERVER_TYPES eType, const std::string& strHashKey, const uint16_t nMsgID, const std::string& strData) = 0;

		virtual void SendBySuit(const FG_SERVER_TYPES eType, const std::string& strHashKey, const uint16_t nMsgID, const std::string& strData) = 0;
		virtual void SendBySuit(const FG_SERVER_TYPES eType, const std::string& strHashKey, const uint16_t nMsgID, const std::string& strData, const GUID id) = 0;

		virtual void SendBySuitWithOutHead(const FG_SERVER_TYPES eType, const int nHashKey32, const uint16_t nMsgID, const std::string& strData) = 0;

		virtual void SendBySuit(const FG_SERVER_TYPES eType, const int nHashKey32, const uint16_t nMsgID, const std::string& strData) = 0;
		virtual void SendBySuit(const FG_SERVER_TYPES eType, const int nHashKey32, const uint16_t nMsgID, const std::string& strData, const GUID id) = 0;

		virtual void SendSuitByPB(const FG_SERVER_TYPES eType, const std::string& strHashKey, const uint16_t nMsgID, const google::protobuf::Message& xData) = 0;
		virtual void SendSuitByPB(const FG_SERVER_TYPES eType, const std::string& strHashKey, const uint16_t nMsgID, const google::protobuf::Message& xData, const GUID id) = 0;

		virtual void SendSuitByPB(const FG_SERVER_TYPES eType, const int nHashKey32, const uint16_t nMsgID, const google::protobuf::Message& xData) = 0;
		virtual void SendSuitByPB(const FG_SERVER_TYPES eType, const int nHashKey32, const uint16_t nMsgID, const google::protobuf::Message& xData, const GUID id) = 0;

		////////////////////////////////////////////////////////////////////////////////
		virtual std::map<int, FG_SHARE_PTR<FragrantGrass::ConnectData>>& GetServerList() = 0;
		virtual FG_SHARE_PTR<ConnectData> GetServerNetInfo(const FG_SERVER_TYPES eType) = 0;
		virtual FG_SHARE_PTR<ConnectData> GetServerNetInfo(const int nServerID) = 0;
		virtual FG_SHARE_PTR<ConnectData> GetServerNetInfo(const INet* pNet) = 0;
	};
}
#endif//FGI_CLUSTER_CLIENT_MODULE_H